package com.liebaut.controller.order;

import com.liebaut.controller.CrudController;
import com.liebaut.dao.order.ArticleDetailsRepository;
import com.liebaut.dao.order.BoxRepository;
import com.liebaut.dao.order.DeliveryOrderRepository;
import com.liebaut.dao.reports.ReportDetailsRepository;
import com.liebaut.exception.RestException;
import com.liebaut.model.order.DeliveryOrder;
import com.liebaut.model.order.article.ArticleDetails;
import com.liebaut.model.order.article.Box;
import com.liebaut.model.reports.ReportDetails;
import com.liebaut.services.IDGeneratorService;
import com.liebaut.services.JasperReportWriter;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.CrudRepository;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import static com.liebaut.util.MapUtil.map;

@Controller
@RequestMapping("/deliveryOrder")
public class DeliveryOrderController extends CrudController<DeliveryOrder, Long> {
    private static final Logger log = LoggerFactory.getLogger(DeliveryOrderController.class);

    @Autowired
    BoxRepository boxRepository;

    @Autowired
    IDGeneratorService idGeneratorService;

    @Autowired
    ArticleDetailsRepository articleDetailsRepository;

    @Autowired
    JasperReportWriter jasperReportWriter;

    @Autowired
    ReportDetailsRepository reportDetailsRepository;

    public DeliveryOrderController() {
    }

    @Autowired
    public DeliveryOrderController(DeliveryOrderRepository repository) {
        super(repository);
    }



    @RequestMapping(value = "{id}/box", method = RequestMethod.POST, consumes = "application/json")
    @ResponseBody
    public Object addBox(@PathVariable Long id, @RequestBody String body) throws IOException {
        try {
            Box box = (Box) new ObjectMapper().readValue(body, Box.class);
            DeliveryOrder order = repository.findOne(id);
            if (order != null && !order.isInvoiced()){
                boxRepository.save(box);
                order.getBoxes().add(box);
                repository.save(order);
                return box;
            } else if(order.isInvoiced()){
                throw new IOException("This delivery order is already invoiced. You cannot make any changes to it anymore.");
            }
            else
                throw new RestException(HttpStatus.NOT_FOUND, "ID not found: " + id);
        } catch (JsonProcessingException e) {
            log.debug("invalid request", e);
            throw new HttpMessageNotReadableException("Invalid request", e);
        }
    }

    @RequestMapping(value = "{id}/box/{boxId}/article", method = RequestMethod.POST, consumes = "application/json")
    @ResponseBody
    public Object addArticle(@PathVariable Long id, @PathVariable Long boxId, @RequestBody String body) throws IOException {
        try{
            ArticleDetails details = new ObjectMapper().readValue(body, ArticleDetails.class);
            Box box = boxRepository.findOne(boxId);
            if(box != null){
                articleDetailsRepository.save(details);
                box.getArticles().add(details);
                boxRepository.save(box);
                return details;
            } else
                throw new RestException(HttpStatus.NOT_FOUND, "ID not found: " + id);
        }  catch (JsonProcessingException e) {
            log.debug("invalid request", e);
            throw new HttpMessageNotReadableException("Invalid request", e);
        }
    }

    @RequestMapping(value = "{id}/box/{boxId}/article", method = RequestMethod.GET)
    @ResponseBody
    public Object getArticles(@PathVariable Long id, @PathVariable Long boxId) throws IOException {
        Box box = boxRepository.findOne(boxId);
        if(box != null){
            return box.getArticles();
        } else
            throw new RestException(HttpStatus.NOT_FOUND, "ID not found: " + id);
    }

    @RequestMapping(value = "{id}/pdf/{reportDetailsId}", method = RequestMethod.GET)
     @ResponseBody
     public void getDeliveryOrderPDF(@PathVariable Long id, @PathVariable Long reportDetailsId, HttpServletResponse response) throws IOException {
        Map<String, Object> reportParameters = new HashMap<String, Object>();
        reportParameters.put("orderId", id);
        ReportDetails details  = reportDetailsRepository.findOne(reportDetailsId);
        if(details != null){
            byte[] pdf = jasperReportWriter.getPDFReport(details.getFilePath(), reportParameters);
            response.setContentType("application/pdf");
            //response.addHeader("Content-Disposition", "attachment; filename=" + "report.pdf");
            response.getOutputStream().write(pdf);
        } else
            throw new RestException(HttpStatus.NOT_FOUND, "Report not found: " + id);

    }

    @Override
    protected DeliveryOrder saveRequestToEntity(String body) throws IOException {
        DeliveryOrder order = super.saveRequestToEntity(body);
        order.setDeliveryNumber(idGeneratorService.getNextNumber("deliveryorder"));
        return order;
    }

}
